對應 30天挑戰精通 PowerShell 該書第 13 章「遠端控制:一對一及一對多」。
今天將書中介紹的 WinRM 概覽及個人使用筆記做整理,也將昨天沒有講完的 PSSession 及 Invoke-Command 做個結尾。
WinRM(Windows Remote Management)是 Microsoft 基於 WS-Management 通訊協定的實作,用於遠端管理 Windows 系統。它允許你透過網路與遠端電腦通訊,執行指令、存取資料,並進行系統管理。
WinRM 不是僅限於 PowerShell 使用。Microsoft 正逐漸將其應用到更多通訊管理方面,甚至包括目前使用其他協定的事物。基於這個理念,Microsoft 讓 WinRM 能夠把流量導引到多種管理應用程式,而不是只有 PowerShell。WinRM 扮演著調度者的角色:當流量導入時,WinRM 會決定哪個應用程式需要處理這些流量。所有的 WinRM 流量都會被標記上「接收的應用程式( recipient application )的名稱」,而這些應用程式必須向 WinRM 註冊為端點( endpoint ),讓 WinRM 能夠代替它們監聽「傳入的流量」。這意味著你需要在啟用 WinRM 的同時,還要指示 PowerShell 向 WinRM 註冊為一個端點。
你的系統上可能有數十個甚至數百個 WinRM 端點( PowerShell 將他們稱為會話組態,session configuration )。每個端點都能指向不同的應用程式,你甚至可以有多個端點指向同一個應用程式,但是提供不同的權限和功能。
在 Client 端以管理者權限開啟 PowerShell 後執行 winrm get winrm/config/client
確認 WinRM client 的設定。
false
。PS C:\Users\kanglin> winrm get winrm/config/client
Client
NetworkDelayms = 5000
URLPrefix = wsman
AllowUnencrypted = false
Auth
Basic = true
Digest = true
Kerberos = true
Negotiate = true
Certificate = true
CredSSP = false
DefaultPorts
HTTP = 5985
HTTPS = 5986
TrustedHosts
在 Server 端以管理者權限開啟 PowerShell 後執行 winrm get winrm/config/service
確認 WinRM Server 端 service 的設定。
PS C:\Users\kanglinserver> winrm get winrm/config/service
Service
RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
MaxConcurrentOperations = 4294967295
MaxConcurrentOperationsPerUser = 1500
EnumerationTimeoutms = 240000
MaxConnections = 300
MaxPacketRetrievalTimeSeconds = 120
AllowUnencrypted = false
Auth
Basic = false
Kerberos = true
Negotiate = true
Certificate = false
CredSSP = false
CbtHardeningLevel = Relaxed
DefaultPorts
HTTP = 5985
HTTPS = 5986
IPv4Filter = *
IPv6Filter = *
EnableCompatibilityHttpListener = false
EnableCompatibilityHttpsListener = false
CertificateThumbprint
AllowRemoteAccess = true
查看所有 WinRM Listener 的詳細信息
PS C:\Users\kanglinserver> winrm enumerate winrm/config/listener
Listener
Address = *
Transport = HTTP
Port = 5985
Hostname
Enabled = true
URLPrefix = wsman
CertificateThumbprint
ListeningOn = 10.1.1.127, 127.0.0.1, ::1
執行該命令將正確設定防火牆規則和服務狀態,以確保 WinRM 正常運行。
Enable-PSRemoting -Force
當 Client 端連接到非同網域的 Server(或工作組環境)時,需要在 Client 端設定 TrustedHosts
允許與指定的遠端電腦進行通訊。
Set-Item WSMan:\localhost\Client\TrustedHosts "遠端電腦的IP或主機名"
在設定完成後,您可以使用 Test-WsMan
命令來確認是否可以與目標 Server 成功連接。
Test-WsMan -ComputerName 遠端電腦的IP或主機名
執行該命令將正確設定防火牆規則和服務狀態,以確保 WinRM 正常運行。
Enable-PSRemoting -Force
winrm enumerate winrm/config/listener
winrm create winrm/config/listener?Address=*+Transport=HTTP
winrm create winrm/config/listener?Address=*+Transport=HTTPS
確保連接 Server 的帳號有足夠的權限執行所需的遠端命令。通常需要管理員權限,特別是對於執行特定的管理任務。然而 Client 若需要使用不同的帳號來連接 Server,可以使用 -Credential
參數來指定憑證。
該範例會跳出輸入帳號密碼的提示字窗
# 取得使用者憑證
$cred = Get-Credential
# 執行遠端指令
Invoke-Command -ComputerName "遠端電腦名或IP" -Credential $cred -ScriptBlock { Get-Process }
該範例會跳出輸入帳號密碼的提示字窗
# 取得使用者憑證
$cred = Get-Credential
# 建立 PSSession
$session = New-PSSession -ComputerName "遠端電腦名或IP" -Credential $cred
# 在 PSSession 中執行指令
Invoke-Command -Session $session -ScriptBlock { Get-Service }
# 關閉 PSSession
Remove-PSSession -Session $session
直接在腳本中指定使用者名稱和密碼,但需要注意安全性。
# 建立安全的密碼字串
$securePassword = ConvertTo-SecureString "您的密碼" -AsPlainText -Force
# 建立憑證物件
$cred = New-Object System.Management.Automation.PSCredential("使用者名稱", $securePassword)
# 使用憑證執行遠端指令
Invoke-Command -ComputerName "遠端電腦名或IP" -Credential $cred -ScriptBlock { Get-Process }
PSSession 是一個與遠端電腦建立的持久連線,允許您在該連線中執行多個指令,而不必每次都重新建立連線。這在需要執行多個指令時可以提高效率。
$session = New-PSSession -ComputerName 遠端電腦的IP或主機名
Get-PSSession
Invoke-Command -Session $session -ScriptBlock { Get-Process }
Enter-PSSession -Session $session
在互動式會話中,輸入 Exit-PSSession
或簡寫 Exit
。
Remove-PSSession -Session $session
# 建立 PSSession
$session = New-PSSession -ComputerName 192.168.1.100
# 在遠端會話中執行指令
Invoke-Command -Session $session -ScriptBlock { Get-Service }
# 關閉 PSSession
Remove-PSSession -Session $session
PS /Users/kanglin/code/30days> get-help Invoke-Command | more
NAME
Invoke-Command
SYNOPSIS
Runs commands on local and remote computers.
-ComputerName
在一台遠端電腦上運行單個命令。New-PSSession
建立持久會話,然後使用 -Session 在會話中多次執行命令,適合多命令操作。Invoke-Command -ComputerName 遠端電腦的IP或主機名 -ScriptBlock { 指令或腳本區塊 }
Invoke-Command -Session $session -ScriptBlock { 指令或腳本區塊 }
Invoke-Command -ComputerName PC1,PC2,PC3 -ScriptBlock { 指令或腳本區塊 }
$computers = @("Server1", "Server2", "Server3")
Invoke-Command -ComputerName $computers -ScriptBlock { Restart-Service -Name "Spooler" }
假設有一個本地腳本 C:\Scripts\Task.ps1
,需要在遠端電腦上執行。
Invoke-Command -ComputerName 192.168.1.100 -FilePath "C:\Scripts\Task.ps1"
在遠端執行命令時,存在一些與本地執行的差異,需要特別注意。
遠端命令返回的物件是「反序列化」的,這意味著它們僅包含屬性值,而沒有方法。這可能影響您對物件的操作,例如無法調用方法或修改屬性。
為了提高效率,應盡量在遠端完成資料處理,減少傳輸到本地的數據量。例如,以下做法更有效:
Invoke-Command -ComputerName Server1 -ScriptBlock { Get-EventLog -LogName System | Where-Object { $_.EventID -eq 100 } }
$events = Invoke-Command -ComputerName Server1 -ScriptBlock { Get-EventLog -LogName System }
$filteredEvents = $events | Where-Object { $_.EventID -eq 100 }
在遠端進行過濾可以減少網路流量,提高執行速度。
對應 30天挑戰精通 PowerShell 該書第 13 章「遠端控制:一對一及一對多」。
WinRM - setup and test on Windows laptop
Windows Remote Management Architecture
Powershell tricks—Powershell Remoting
about_PSSessions
PowerShell Remoting (PSRemoting) Explained: Ultimate Guide
Day 16 - 利用背景作業進行多工處理